﻿namespace TestTool.HttpTransport
{
    using System;
    using System.Collections.ObjectModel;
    using System.ServiceModel;
    using System.ServiceModel.Channels;

    internal class HttpChannelFactory : ChannelFactoryBase<IRequestChannel>
    {
        private TestTool.HttpTransport.HttpTransportBindingElement _bindingElement;
        private System.ServiceModel.Channels.BufferManager _bufferManager;
        private System.ServiceModel.Channels.MessageEncoderFactory _messageEncoderFactory;

        internal HttpChannelFactory(TestTool.HttpTransport.HttpTransportBindingElement bindingElement, BindingContext context) : base(context.Binding)
        {
            this._bufferManager = System.ServiceModel.Channels.BufferManager.CreateBufferManager(bindingElement.MaxBufferPoolSize, 0x7fffffff);
            Collection<MessageEncodingBindingElement> collection = context.BindingParameters.FindAll<MessageEncodingBindingElement>();
            if (collection.Count > 1)
            {
                throw new InvalidOperationException("More than one MessageEncodingBindingElement was found in the BindingParameters of the BindingContext");
            }
            if (collection.Count == 1)
            {
                this._messageEncoderFactory = collection[0].CreateMessageEncoderFactory();
            }
            else
            {
                this._messageEncoderFactory = CustomHttpConstants.DefaultMessageEncoderFactory;
            }
            this._bindingElement = bindingElement;
        }

        public override T GetProperty<T>() //where T: class
        {
            T property = this.MessageEncoderFactory.Encoder.GetProperty<T>();
            if (property != null)
            {
                return property;
            }
            if (typeof(T) == typeof(MessageVersion))
            {
                return (T)(object)this.MessageEncoderFactory.Encoder.MessageVersion;
            }
            return base.GetProperty<T>();
        }

        protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return new CompletedAsyncResult(callback, state);
        }

        protected override void OnClosed()
        {
            base.OnClosed();
            this._bufferManager.Clear();
        }

        protected override IRequestChannel OnCreateChannel(EndpointAddress remoteAddress, Uri via)
        {
            return new HttpRequestChannel(this, remoteAddress, via, this._messageEncoderFactory.Encoder, this._bindingElement);
        }

        protected override void OnEndOpen(IAsyncResult result)
        {
            CompletedAsyncResult.End(result);
        }

        protected override void OnOpen(TimeSpan timeout)
        {
        }

        public System.ServiceModel.Channels.BufferManager BufferManager
        {
            get
            {
                return this._bufferManager;
            }
        }

        public System.ServiceModel.Channels.MessageEncoderFactory MessageEncoderFactory
        {
            get
            {
                return this._messageEncoderFactory;
            }
        }
    }
}

